Skip to content

DATAES-771 - Add after-save entity callbacks support. #414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2020

Conversation

rpuch
Copy link
Contributor

@rpuch rpuch commented Mar 28, 2020

This change enables to get callbacks when an entity gets saved to Elasticsearch.

Comparing to AfterSaveCallback in spring-data-mongodb (that was used for inspiration), AfterSaveCallback added in this PR has a simpler method signature: it does not have neither document (because Elasticsearch does not return an indexed document in a response from index operation) nor collection arguments. We can add index instead of collection though. I need your input on this matter.

Also, I'm going to add support for after-convert callbacks in the next PR if everything goes well with this one.

  • You have read the Spring Data contribution guidelines.
  • There is a ticket in the bug tracker for the project in our JIRA.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

Copy link
Collaborator

@sothawo sothawo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some naming stuff, and a nullability check.

protected <T> T maybeCallbackAfterSave(T entity) {

if (entityCallbacks != null) {
return entityCallbacks.callback(AfterSaveCallback.class, entity);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make sure that the value returned from the callback is not null. Although the API has neither the parameter or return value marked as nullable, we might get a null value by some bad implemention of an after-save callback. So I think we should assert this here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code of SimpleEntityCallbackInvoker, it looke like it makes sure that the value returned by a callback is non-null:

				throw new IllegalArgumentException(
						String.format("Callback invocation on %s returned null value for %s", callback.getClass(), entity));

Also, javadoc for EntityCallbackInvoker#invokeCallback() says that the returned value is 'never null'.
So even a callback that returns null will just cause an exception somewhere in EntityCallbacks implementation, and here we will not get a null value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I didn't dig this deep into the code for this PR, sorry (wish this were Kotlin stuff!), so that's ok


// suppressing because it's either entity itself or something of a correct type returned by an entity callback
@SuppressWarnings("unchecked")
T castResult = (T) query.getObject();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must not be null, see my comment for the maybeCallbackAfterSave(T entity) method.

Copy link
Contributor Author

@rpuch rpuch Mar 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query.getObject() can be null either if entity is null (which is impossible, there is an assertion in the beginning of the method), or if entityCallbacks.callback() returns null (which is also impossible).
So the castResult cannot be null.

Would you still prefer to assert that it is not null, just in case?

@@ -151,7 +158,10 @@ public void setEntityCallbacks(EntityCallbacks entityCallbacks) {
});
}

return entities;
return indexQueries.stream()
.map(IndexQuery::getObject)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must not be null, see my comment for the maybeCallbackAfterSave(T entity) method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, this can only be null if some entity in the original Iterable is null.

Do you still suggest adding a non-null assertion?

*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class ElasticsearchTransportTemplateUnitTests {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be ElasticsearchTransportTemplateCallbackTests, see my comment for the ElasticsearchRestTemplateUnitTests class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the test suite to ElasticsearchTransportTemplateCallbackTests, thanks for the suggestion

*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class ElasticsearchRestTemplateUnitTests {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be better named ElasticsearchRestTemplateCallbackTests, otherwise it will be confusing with the already existing ElasticsearchTransportTemplateTests, and this class is especially for the callbacks. For the reactive part you have named it according to this pattern as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the suite to ElasticsearchRestTemplateCallbackTests, thanks for the suggestion

This change enables to get callbacks when an entity gets saved to Elasticsearch.
@rpuch
Copy link
Contributor Author

rpuch commented Mar 29, 2020

Thank you for your review, @sothawo !

I've renamed the test suites.

Concerning the null-checks, please see my comments.

@sothawo sothawo merged commit c73d197 into spring-projects:master Mar 29, 2020
@sothawo
Copy link
Collaborator

sothawo commented Mar 29, 2020

thanks a lot, this is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants